LScript Tutorial #2
Tutorial Page Previous Tutorial Next Tutorial

Creating A Helix Curve

This tutorial will create a Modeler LScript that will create a helix-shaped
curve.

First, we begin by creating the script shell that all Modeler LScripts must
use. The shell is the name main following by the body of the
function.


        main
        {
           ...
        }

The first thing we need to do in our function is switch the script into "mesh edit"
mode by making a call to the LScript function editbegin(). It is in
this mode that we modify Modeler's mesh data, by adding, deleting or moving things
like points, polygons and curves. If we attempt to perform any of these operations
without being in "mesh edit" mode, LScript will generate an error, and terminate our
script.

Each call to editbegin() should be matched by a terminating call
to editend(). Until you invoke editend() with a true
flag, your mesh edit operations will not be applied the the active Modeler layers.
This allows you to abort any changes you may have made to existing mesh data by calling
editend() with a false flag.


        main
        {
           editbegin();
           ...
           editend();
        }

The astute reader will notice that we didn't provide a flag parameter to the
editend() call in the code fragment above. The reason for this is
that this parameter is optional, and the default value used if the parameter is
not provided is true.

Now that we are in "mesh edit" mode, we can begin adding data to Modeler's active
foreground layer(s). Please note that, in this tutorial, we are assume that the
script user has already selected the layer or layers into which they wish this
data to be placed. In the next tutorial, we will set layers for ourselves as
the script performs its processing.

In order to create a helix curve, we must decide upon the value of a number of
variables that will be used to contruct the coil. These variables are:

  1. the number of points along the coil
  2. the number of degrees between each point
  3. the increment in positive-Y units for the height of the coil
  4. the radius of each point from the center of the coil
  5. where the initial point will be placed
Before we determine these factors, however, we know that we will probably have
to perform a loop within our script to process each successive point that is
added to the coil. The loop control that we will use will be a
for() loop. This type of loop control is quite similar to that
used by the C language, and it contains all of the looping conditions in a single
statement.


        main
        {
           editbegin();
           ...
           for(x = 2;x <= TOTALPOINTS;x++)
           {
               ...
           }
           ...
           editend();
        }

Notice in the above code fragment that we have hard-coded the initial value of our
loop-counter variable x to be "2". The reason for this will be clearer
as the body of our script evolves.

Now, we must take a moment and determine the shaping factors of our curve. In our
script, we want the helix coil to curve about the Y axis a full 360 degrees from its
starting point. To create a smooth curve, we will place points along the coil every
30 degrees. By dividing 360 by 30, we find that we will need a total of 12 points
on our helix. As we construct our helix, we will cause it to rise along the Y axis
by 10 cm (or .1 meters) at each step. Our radius from the center of the coil
will be .5 meters.

Let's look at the values that we will be using to contruct this helix curve:

number of points ... 12
number of degrees between each point ... 30
the increment in positive-Y units ... 10 cm (or .1 meters)
the radius of each point from the center of the coil ... 50 cm (or .5 meters)
where the initial point will be placed ... <.5,0,0>

Now, we can convert these values into script code.

First, we will add macros to represent the number of points our helix coil
will contain, the number of degrees in each step, and the increment along
the Y axis. This is placed at the top of our script code.



        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();
           ...
           for(x = 2;x <= TOTALPOINTS;x++)
           {
               ...
           }
           ...
           editend();
        }

We use macros not only to make the script code more readable, but more
importantly to help localize changes to our script code. In our current
script, we only use the point count and height increment in one location,
so it would be easy enough to change it if we wished. However, in larger,
more-complex scripts we might use the point-count value in many different
locations (like the degree step is used in our script). If we were required
to change all these locations each time we wanted to change the number of
points generated, we would not only have a lot more work on our hands, but
there is an increasing possibility that we could miss some locations or even
type in the wrong number at one of them! By using macros, we merely change
the value in one location, and all instances of the macro name are updated
accordingly.

Next, we will create a variable to hold the current point position. We then
use that point location to create an actual point within Modeler by calling the
addpoint() LScript function. The return value of this function is
an identifier for the newly-created point, and is assigned to the first element
of our point id array. We use an array to remember all the point ids returned
to us by Modeler as we create new points. We then use all these point ids to
create a new curve at the end of our script:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               ...
           }
           ...
           editend();
        }

From the code fragment above, you can now see why the loop counter begins
at "2" instead of "1". We have already assigned a value to the first element
in our array, our anchor point, and need to continue assigning with the
second and subsequent elements. We accomplish this within our for()
loop control.

Two more variables are used for the calculations within our for()
loop. These values hold the radius and absolute degrees of the current point.
Because these values change or must be caculated during the course of the script's
execution, they cannot be placed into macros:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z));
           degrees = DEGSTEP;

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               ...
           }
           ...
           editend();
        }

The radius calculation seems slightly useless because we have already determined that
our radius will be .5 meters from the center. However, if at some later time find yourself
dealing with an unknown initial point value (perhaps you've allowed the user to place
the initial point), then you will not have a clear idea of the radius. The calculation
used above will always determine the correct radius, regardless of where the point
is initially placed.

At this point in our script, we have our first point along the helix coil. This first
point is our anchor. Now, within the for() loop, we will place the remaining
11 points into Modeler. The first thing we do for each successive point is move it along
the positive-Y axis by our pre-defined increment value:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z));
           degrees = DEGSTEP;

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               thepoint.y += HEIGHTINCR;
               ...
           }
           ...
           editend();
        }

Next, we perform some trigonometric calculations to determine where the
new point will lie along the helix curve:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z));
           degrees = DEGSTEP;

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               thepoint.y += HEIGHTINCR;

               thepoint.x = radius * cos(rad(degrees));
               thepoint.z = radius * sin(rad(degrees));
               ...
           }
           ...
           editend();
        }

We then add this new point into Modeler's mesh data, and increment the sweep around
the coil by the degree value:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z));
           degrees = DEGSTEP;

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               thepoint.y += HEIGHTINCR;

               thepoint.x = radius * cos(rad(degrees));
               thepoint.z = radius * sin(rad(degrees));

               pnt[x] = addpoint(thepoint);

               degrees += DEGSTEP;
           }
           ...
           editend();
        }

Finally, we add a call to LScript's addcurve(), passing to it
our array of point identifiers. Modeler will then create our helix curve
from the points we just created:


        @define TOTALPOINTS  12
        @define DEGSTEP      30
        @define HEIGHTINCR   .1

        main
        {
           editbegin();

           thepoint = <.5,0,0>;
           pnt[1] = addpoint(thepoint);

           radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z));
           degrees = DEGSTEP;

           for(x = 2;x <= TOTALPOINTS;x++)
           {
               thepoint.y += HEIGHTINCR;

               thepoint.x = radius * cos(rad(degrees));
               thepoint.z = radius * sin(rad(degrees));

               pnt[x] = addpoint(thepoint);

               degrees += DEGSTEP;
           }

           addcurve(pnt);

           editend();
        }


Tutorial Page Previous Tutorial Next Tutorial
© 1997 NewTek, Inc.